//-
// ==========================================================================
// Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors.  All 
// rights reserved.
//
// The coded instructions, statements, computer programs, and/or related 
// material (collectively the "Data") in these files contain unpublished 
// information proprietary to Autodesk, Inc. ("Autodesk") and/or its 
// licensors, which is protected by U.S. and Canadian federal copyright 
// law and by international treaties.
//
// The Data is provided for use exclusively by You. You have the right 
// to use, modify, and incorporate this Data into other products for 
// purposes authorized by the Autodesk software license agreement, 
// without fee.
//
// The copyright notices in the Software and this entire statement, 
// including the above license grant, this restriction and the 
// following disclaimer, must be included in all copies of the 
// Software, in whole or in part, and all derivative works of 
// the Software, unless such copies or derivative works are solely 
// in the form of machine-executable object code generated by a 
// source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. 
// AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED 
// WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF 
// NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
// PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR 
// TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS 
// BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, 
// DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK 
// AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY 
// OR PROBABILITY OF SUCH DAMAGES.
//
// ==========================================================================
//+

//
// This example takes a curve and changes it into a helix.
//

#include <maya/MIOStream.h>
#include <math.h>

#include <maya/MFnPlugin.h>
#include <maya/MFnNurbsCurve.h>
#include <maya/MPointArray.h>
#include <maya/MDoubleArray.h>
#include <maya/MPoint.h>
#include <maya/MSelectionList.h>
#include <maya/MItSelectionList.h>
#include <maya/MItCurveCV.h>
#include <maya/MGlobal.h>
#include <maya/MDagPath.h>
#include <maya/MString.h>
#include <maya/MPxCommand.h>
#include <maya/MArgList.h>

class helix2 : public MPxCommand
{

public:
				helix2();
	virtual		~helix2();

	MStatus		doIt( const MArgList& );
	MStatus		redoIt();
	MStatus		undoIt();
	bool		isUndoable() const;

	static		void* creator();

private:
	MDagPath	fDagPath;
	MObject 	fComponent;
	MPointArray	fCVs;
	double		radius;
	double		pitch;
};

MStatus helix2::doIt( const MArgList& args )
{
	MStatus status;

	// Parse the arguments.
	for ( unsigned i = 0; i < args.length(); i++ ) {
		if ( MString( "-p" ) == args.asString( i, &status )
				&& MS::kSuccess == status)
		{
			double tmp = args.asDouble( ++i, &status );
			if ( MS::kSuccess == status )
				pitch = tmp;
		}
		else if ( MString( "-r" ) == args.asString( i, &status )
				&& MS::kSuccess == status)
		{
			double tmp = args.asDouble( ++i, &status );
			if ( MS::kSuccess == status )
				radius = tmp;
		} else {
			MString msg = "Invalid flag: ";
			msg += args.asString( i );
			displayError( msg );
			return MS::kFailure;
		}
	}

	// Get the first selected curve from the selection list.
	MSelectionList slist;
	MGlobal::getActiveSelectionList( slist );

	MItSelectionList	list( slist, MFn::kNurbsCurve, &status );
	if (MS::kSuccess != status) {
		cerr << "doIt: could not create selection list iterator\n";
		return status;
	}

	if (list.isDone()) {
		cerr << "doIt: no curve has been selected\n";
		return MS::kFailure;
	}

	list.getDagPath( fDagPath, fComponent );

	return redoIt();
}

MStatus helix2::redoIt()
{
	unsigned		i, numCVs;
	MStatus			status;
	MFnNurbsCurve   curveFn( fDagPath );

	numCVs = curveFn.numCVs();
	status = curveFn.getCVs( fCVs );
	if ( MS::kSuccess != status )
	{
		cerr << "redoIt: could not get cvs status: " << status << endl;
		return MS::kFailure;
	}

	MPointArray		points(fCVs);
	for (i = 0; i < numCVs; i++)
		points[i] = MPoint( radius * cos( (double)i ),
							pitch * (double)i,
							radius * sin( (double)i ) );
	status = curveFn.setCVs( points );
	if ( MS::kSuccess != status )
	{
		cerr << "redoIt: could not setCVs status: " << status << endl;
		fCVs.clear();
		return status;
	}

	status == curveFn.updateCurve();
	if ( MS::kSuccess != status )
	{
		cerr << "redoIt: updateCurve() failed status: " << status << endl;
		return status;
	}

	return MS::kSuccess;
}

MStatus helix2::undoIt()
{
	MStatus		status;

	MFnNurbsCurve	curveFn( fDagPath );
	status = curveFn.setCVs( fCVs );
	if ( MS::kSuccess != status)
	{
		cerr << "undoIt: array length is " << fCVs.length()
		     << "bad status: " << status << endl;
		return status;
	}

	status = curveFn.updateCurve();
	if ( MS::kSuccess != status )
	{
		cerr << "undoIt: updateCurve() failed status: " << status << endl;
		return status;
	}

	fCVs.clear();
	return MS::kSuccess;
}

void* helix2::creator()
{
	return new helix2();
}

helix2::helix2()
	: radius( 4.0 ),
	  pitch( 0.5 ),
	  fComponent()
{}

helix2::~helix2()
{
	fCVs.clear();
	// Note that we do nothing with fComponent which is owned by Maya.
}

bool helix2::isUndoable() const
{
	return true;
}

MStatus initializePlugin( MObject obj )
{ 
	MStatus   status;
	MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");

	status = plugin.registerCommand( "helix2", helix2::creator );
	if (!status) {
		status.perror("registerCommand");
		return status;
	}

	return status;
}

MStatus uninitializePlugin( MObject obj )
{
	MStatus   status;
	MFnPlugin plugin( obj );

	status = plugin.deregisterCommand( "helix2" );
	if (!status) {
		status.perror("deregisterCommand");
		return status;
	}

	return status;
}
